#define MAX_LINE_SIZE (MAX_INTPUT_SIZE - 2) + MAX_HASH_SIZE + 1

#include "../Misc/part1_shared.h"

void read_hash(FILE *file, char *hash_function);
int read_line(FILE *file, char *buffer);
void set_file_pointer_to_start(FILE *file);
int validate_passwords_file(FILE *file);

int main(int argc, char **argv)
{
	char *users_file_path = argv[1];
	char user_input[MAX_INTPUT_SIZE];
	char file_line[MAX_LINE_SIZE];
	char username[MAX_INTPUT_SIZE];
	char password[MAX_INTPUT_SIZE];
	char file_username[MAX_INTPUT_SIZE];
	char file_password[MAX_HASH_SIZE] ;
	char hashed_password[MAX_HASH_SIZE];
	BasicHashFunctionPtr hash = NULL;
	char hash_function[5];
	int valid_input = 0, valid_file = 1;
	FILE *file;
	int bRes = 1;

	if (argc != 2) {
		fprintf(stderr ,"Error: Usage authenticate <authentication table text file>\n");
		exit(1);
	}

	file = fopen(users_file_path,"r");
	if (file == NULL) {
		perror(users_file_path);
		exit(1);
	}

	valid_file = validate_passwords_file(file);
	if (!valid_file) {
		fprintf(stderr, "Error: %s is not a valid passwords file\n", users_file_path);
		exit(1);
	}

	
	read_hash(file, hash_function);
	if (*hash_function == 'M') {
		hash = MD5BasicHash;
	}
	if (*hash_function == 'S'){
		hash = SHA1BasicHash;
	}

	while (1) {
		printf(">>");
		if (read_input(user_input) == -1) continue;
		if (!strcmp(user_input, "quit")) {
			exit(1);
		}
		valid_input = extract_username_and_passowrd(user_input,username,password);
		if (valid_input) {
			while (1) {
				bRes = read_line(file, file_line);
				if (!bRes) { 
					printf("Denied\n");
					set_file_pointer_to_start(file);
					break;
				}
				extract_username_and_passowrd(file_line,file_username,file_password);
				hash_password(hash, password,hashed_password);
				if ((!strncmp(username,file_username,MAX_INTPUT_SIZE)) &&  (!strncmp(hashed_password,file_password,MAX_HASH_SIZE))) {
					printf("Approved\n");
					set_file_pointer_to_start(file);
					break;
				}
			}
		}
		else {
			fprintf(stderr, "Error: Commands are either \"quit\" or <user name>tab<password>\n");
		}
	}
	return 0;
}

int validate_passwords_file(FILE *file) {
	char hash_function[MAX_LINE_SIZE] = "";
	char file_line[MAX_LINE_SIZE] = "";
	char username[MAX_INTPUT_SIZE - 2] = "";
	char password[MAX_HASH_SIZE] = "";
	int line = 1, input = 0, i = 0;
	int password_expected_size = 0;
	
	/* verify that a we support the hash function */
	read_line(file, hash_function);
	if (strcmp(hash_function,"MD5") && strcmp(hash_function,"SHA1")) {
		return 0;
	}
	if (!strcmp(hash_function,"MD5")) password_expected_size = MD5_OUTPUT_LENGTH_IN_BYTES * 2 + 1;
	if (!strcmp(hash_function,"SHA1")) password_expected_size = SHA1_OUTPUT_LENGTH_IN_BYTES * 2 + 1;

	/* verify each line is valid */ 
	while (line) {
		line = read_line(file, file_line);
		input = extract_username_and_passowrd(file_line,username,password);
		if (!input) {
			return 0;
		}
		/* accept only hexa little endian format passwords */
		if (string_length(password) == password_expected_size) {
			i = 0;
			while (password[i] != '\0') {
				if ((password[i] < '0') || (password[i] > '9')) {
					if ((password[i] != 'a') && (password[i] != 'b') && (password[i] != 'c')
						&& (password[i] != 'd') && (password[i] != 'e') && (password[i] != 'f')) {
						return 0;
					}
				}
				i++;
			}
		}
		else return 0;

	}
	fseek(file,0,SEEK_SET);
	return 1;
}

int read_line(FILE *file, char *buffer) {
	fseek(file,0,SEEK_CUR);
	if (fgets(buffer,MAX_LINE_SIZE,file) == NULL) return 0;
	buffer[string_length(buffer) - 2] = '\0';
	return 1;
}

void read_hash(FILE *file, char *hash_function) {
	fseek(file,0,SEEK_CUR);
	fgets(hash_function,5, file);
}

void set_file_pointer_to_start(FILE *file) {
	fseek(file,0,SEEK_SET);
}

